/**
 * Created by yuris on 04.12.14.
 */
package model.objects {
import flash.geom.Point;
import flash.geom.Point;

import signals.UpdateDataSignal;

public class ShopDesignData {
    public var sizeX:int;
    public var sizeY:int;

    private var _stdFloor:String;
    private var _stdWall:String;

    private var _floorData:Vector.<Vector.<String>>;

    private var _wallDataX:Vector.<String>;
    private var _wallDataY:Vector.<String>;

    private var _doorDataX:Vector.<String>;
    private var _doorDataY:Vector.<String>;

    private var _wallCoverDataX:Vector.<String>;
    private var _wallCoverDataY:Vector.<String>;

    private var _updateSignal:UpdateDataSignal = new UpdateDataSignal();

    public static const SIGNAL_UPDATE_FLOOR:String = "SIGNAL_UPDATE_FLOOR";
    public static const SIGNAL_UPDATE_WALL:String = "SIGNAL_UPDATE_WALL";
    public static const SIGNAL_UPDATE_WALL_COVER:String = "SIGNAL_UPDATE_WALL_COVER";
    public static const SIGNAL_UPDATE_WALL_MASK:String = "SIGNAL_UPDATE_WALL_MASK";
    public static const SIGNAL_UPDATE_DOORS:String = "SIGNAL_UPDATE_DOORS";

    public function ShopDesignData(sizeX:String, sizeY:String, stdFloor:String, stdWall:String) {
        this.sizeX = int(sizeX);
        this.sizeY = int(sizeY);
        this._stdFloor = stdFloor;
        this._stdWall = stdWall;

        var x:int,y:int;
        this._floorData = new Vector.<Vector.<String>>();
        for(x = 0;x < this.sizeX; x++){
            _floorData.push(new Vector.<String>());
            for(y = 0 ;y < this.sizeY; y++){
                _floorData[x].push(this._stdFloor);
            }
        }

        this._wallDataX = new Vector.<String>();
        this._doorDataX = new Vector.<String>();
        for(x = 0 ;x < this.sizeX; x++){
            this._wallDataX.push(this._stdWall);
            this._doorDataX.push(null);
        }
        this._wallDataY = new Vector.<String>();
        this._doorDataY = new Vector.<String>();
        for(y = 0;y < this.sizeY; y++){
            this._wallDataY.push(this._stdWall);
            this._doorDataY.push(null);
        }


        this._wallCoverDataX = new <String>[];
        for(x = 0 ;x < this.sizeX; x++){
            this._wallCoverDataX.push(null);
        }
        this._wallCoverDataY = new <String>[];
        for(y = 0 ;y < this.sizeY; y++){
            this._wallCoverDataY.push(null);
        }
    }

    public function getFloorAt(quadCoord:Point):String{
        if(quadCoord.x < 0 || quadCoord.y < 0 || this._floorData.length <= quadCoord.x || this._floorData.length == 0 || this._floorData[0].length <= quadCoord.y){
            return null;
        }
        var _result:String = this._floorData[quadCoord.x][quadCoord.y];
        if(_result == null){
            _result = this._stdFloor;
        }
        return _result;
    }
    public function setFloorAt(quadCoord:Point, fullSpriteName:String):void{
        this._floorData[quadCoord.x][quadCoord.y] = fullSpriteName;
        this._updateSignal.sendSignal(SIGNAL_UPDATE_FLOOR,{quad:quadCoord, floor_sprite:fullSpriteName});
    }


    public function getWallAtX(xCoord:int):String{
        if(this._indexInRange(xCoord, this._wallDataX) == false) return null;
        var _result:String = this._wallDataX[xCoord];
        if(_result == null){
            _result = this._stdWall;
        }
        return _result;
    }
    public function setWallAtX(xCoord:int, fullSpriteName:String):void{
       this._wallDataX[xCoord] = fullSpriteName;
       this._updateSignal.sendSignal(SIGNAL_UPDATE_WALL,{side:"x",quad:new Point(xCoord,0), wall_data:this._wallDataX, wall_cover_data:this._wallCoverDataX});
    }


    public function getWallAtY(yCoord:int):String{
        if(this._indexInRange(yCoord, this._wallDataY) == false) return null;
        var _result:String = this._wallDataY[yCoord];
        if(_result == null){
            _result = this._stdWall;
        }
        return _result;
    }
    public function setWallAtY(yCoord:int, fullSpriteName:String):void{
        this._wallDataY[yCoord] = fullSpriteName;
        this._updateSignal.sendSignal(SIGNAL_UPDATE_WALL,{side:"y",quad:new Point(0,yCoord), wall_data:this._wallDataY, wall_cover_data:this._wallCoverDataY});
    }



    public function setDoorAtQuad(quad:Point, textureName:String):Boolean {
        if(quad.y == -1){
            return this.setDoorAtX(quad.x,textureName);
        } else if(quad.x == -1){
            return this.setDoorAtY(quad.y,textureName);
        }
        return false;
    }
    public function setDoorAtX(xCoord:int,fullSpriteName:String):Boolean{
        if(this._indexInRange(xCoord, this._doorDataX) == false) return false;
        this._doorDataX[xCoord] = fullSpriteName;
        this._updateSignal.sendSignal(SIGNAL_UPDATE_DOORS,{side:"x",quad:new Point(xCoord,-1), door_data_x:this._doorDataX, door_data_y:this._doorDataY});
        this._updateSignal.sendSignal(SIGNAL_UPDATE_WALL_MASK,{side:"x",quad:new Point(xCoord,0), wall_data:this.wallMaskX, wall_cover_data:this._wallCoverDataX})

        return true;
    }
    public function setDoorAtY(yCoord:int,fullSpriteName:String):Boolean{
        if(this._indexInRange(yCoord, this._doorDataY) == false) return false;
        this._doorDataY[yCoord] = fullSpriteName;
        this._updateSignal.sendSignal(SIGNAL_UPDATE_DOORS,{side:"y",quad:new Point(-1, yCoord), door_data_x:this._doorDataX, door_data_y:this._doorDataY});
        this._updateSignal.sendSignal(SIGNAL_UPDATE_WALL_MASK,{side:"y",quad:new Point(0, yCoord), wall_data:this.wallMaskY, wall_cover_data:this._wallCoverDataY})

        return true;
    }


    public function getDoorAtQuad(quad:Point):String {
        if(quad.y == -1){
            return this.getDoorAtX(quad.x);
        } else if(quad.x == -1){
            return this.getDoorAtY(quad.y);
        }
        return null;
    }
    public function getDoorAtX(xCoord:int):String{
        if(xCoord < 0 || xCoord >= this._doorDataX.length){
            return null
        }
        return this._doorDataX[xCoord];
    }
    public function getDoorAtY(yCoord:int):String{
        if(yCoord <= 0 || yCoord >= this._doorDataY.length){
            return null
        }
        return this._doorDataY[yCoord];
    }

    public function get doorsCount():int {
        var _result:int = 0;
        var i:int = 0;
        for (i = 0; i < _doorDataX.length; i++) {
            if(_doorDataX[i] != null){
                _result ++;
            }
        }
        for (i = 0; i < _doorDataY.length; i++) {
            if(_doorDataY[i] != null){
                _result ++;
            }
        }
        return _result;
    }



    public function getWallCoverAtQuad(quad:Point):String {
        if(quad.y == -1){
            return getWallCoverAtX(quad.x);
        } else if(quad.x == -1){
            return getWallCoverAtY(quad.y);
        }
        return null;
    }
    public function getWallCoverAtX(xCoord:int):String{
       if(this._indexInRange(xCoord, this._wallCoverDataX) == false) return null;
        var _result:String = this._wallCoverDataX[xCoord];
        return _result;
    }
    public function getWallCoverAtY(yCoord:int):String{
        if(this._indexInRange(yCoord, this._wallCoverDataY) == false) return null;
        var _result:String = this._wallCoverDataY[yCoord];
        return _result;
    }


    public function setWallCoverAtQuad(quad:Point, textureName:String):Boolean {
        if(quad.y == -1){
            return setWallCoverAtX(quad.x,textureName);
        } else if(quad.x == -1){
            return setWallCoverAtY(quad.y,textureName);
        }
        return false;
    }
    public function setWallCoverAtX(xCoord:int, fullSpriteName:String):Boolean{
        if(this._indexInRange(xCoord, this._wallCoverDataX) == false) return false;

        this._wallCoverDataX[xCoord] = fullSpriteName;
        this._updateSignal.sendSignal(SIGNAL_UPDATE_WALL_COVER,{side:"x",quad:new Point(xCoord,0), wall_data:this._wallDataX, wall_cover_data:this._wallCoverDataX})
        return true;
    }
    public function setWallCoverAtY(yCoord:int, fullSpriteName:String):Boolean{
        if(this._indexInRange(yCoord, this._wallCoverDataY) == false) return false;

        this._wallCoverDataY[yCoord] = fullSpriteName;
        this._updateSignal.sendSignal(SIGNAL_UPDATE_WALL_COVER,{side:"y",quad:new Point(0,yCoord), wall_data:this._wallDataY, wall_cover_data:this._wallCoverDataY})
        return true;
    }




    public function quadIsInside(xQuad:int,yQuad:int):Boolean{
        if(xQuad < 0 || xQuad >= sizeX){
            return false
        }
        if(yQuad < 0 || yQuad >= sizeY){
            return false;
        }
        return true;
    }

    public function get floorData():Vector.<Vector.<String>> {
        return this._floorData;
    }

    public function get stdFloor():String {
        return this._stdFloor;
    }

    public function get stdWall():String {
        return this._stdWall;
    }

    public function get wallMaskX():Vector.<String> {
        var _result:Vector.<String> = new Vector.<String>();
        for(var i:int = 0; i < this._wallDataX.length; i++){
            if(this._doorDataX[i] == null){
                _result.push(this._wallDataX[i]);
            } else {
                _result.push(null);
            }
        }
        return _result;
    }
    public function get wallMaskY():Vector.<String> {
        var _result:Vector.<String> = new Vector.<String>();
        for(var i:int = 0; i < this._wallDataY.length; i++){
            if(this._doorDataY[i] == null){
                _result.push(this._wallDataY[i]);
            } else {
                _result.push(null);
            }
        }
        return _result;
    }
    public function get wallDataXFull():Vector.<String> {
        return _wallDataX;
    }
    public function get wallDataYFull():Vector.<String> {
        return _wallDataY;
    }

    public function getDoorPoints():Vector.<Point> {
        var _result:Vector.<Point> = new <Point>[];
        var i:int = 0;
        for (i = 0; i < _doorDataX.length; i++) {
            if(_doorDataX[i] != null){
                _result.push(new Point(i,0));
            }
        }
        for (i = 0; i < _doorDataY.length; i++) {
            if(_doorDataY[i] != null){
                _result.push(new Point(0,i));
            }
        }
        return _result;
    }

    public function isDoorPoint(quad:Point):Boolean {
        if(quad.y == 0 || quad.y == -1){
            if(quad.x > 0 && quad.x < this._doorDataX.length && this._doorDataX[quad.x] != null){
                return true;
            }
        }
        if(quad.x == 0 || quad.x == -1){
            if(quad.y > 0 && quad.y < this._doorDataY.length && this._doorDataY[quad.y] != null){
                return true;
            }
        }
        return false;
    }

    public function isThroughWall(currentQuad:Point,targetQuad:Point):Boolean {
       if(quadIsInside(currentQuad.x,currentQuad.y) != quadIsInside(targetQuad.x,targetQuad.y) ){
           if(getDoorAtQuad(currentQuad) != null || getDoorAtQuad(targetQuad) != null){
               return false;
           } else {
               return true;
           }
       }
        return false;
    }

    public function get wallCoverDataX():Vector.<String> {
        return this._wallCoverDataX;
    }
    public function get wallCoverDataY():Vector.<String> {
        return this._wallCoverDataY;
    }

    public function get doorDataX():Vector.<String> {
        return this._doorDataX;
    }
    public function get doorDataY():Vector.<String> {
        return this._doorDataY;
    }

    public function get updateSignal():UpdateDataSignal {
        return _updateSignal;
    }



    private function _indexInRange(index:int, vector:Object):Boolean {
        if(index < 0 || index >= vector.length){
            return false;
        }
        return true;
    }
}
}
